home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / gnome-games / aisleriot / games / forty_thieves.scm < prev    next >
Encoding:
Text File  |  2009-04-14  |  13.7 KB  |  446 lines

  1. ; AisleRiot - forty_thieves.scm
  2. ; Copyright (C) 2008 Ed Sirett  <ed@makewrite.demon.co.uk>
  3. ;
  4. ; This game is free software; you can redistribute it and/or modify
  5. ; it under the terms of the GNU General Public License as published by
  6. ; the Free Software Foundation; either version 2, or (at your option)
  7. ; any later version.
  8. ;
  9. ; This program is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ; GNU General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU General Public License
  15. ; along with this program; if not, write to the Free Software
  16. ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  17. ; USA
  18.  
  19. (define (new-game)
  20.   (initialize-playing-area)
  21.   (set-ace-low)
  22.   (make-standard-double-deck)
  23.   (shuffle-deck)
  24.  
  25.   (add-normal-slot DECK)
  26.  
  27.   (add-blank-slot)
  28. ; the foundations
  29.   (add-normal-slot '())
  30.   (add-normal-slot '())
  31.   (add-normal-slot '())
  32.   (add-normal-slot '())
  33.   (add-normal-slot '())
  34.   (add-normal-slot '())
  35.   (add-normal-slot '())
  36.   (add-normal-slot '())
  37.  
  38.   (add-carriage-return-slot)
  39. ; the waste pile
  40.   (add-extended-slot '() right)
  41.   (add-carriage-return-slot)
  42.  
  43. ; the tableau
  44.   (add-extended-slot '() down)
  45.   (add-extended-slot '() down)
  46.   (add-extended-slot '() down)
  47.   (add-extended-slot '() down)
  48.   (add-extended-slot '() down)
  49.   (add-extended-slot '() down)
  50.   (add-extended-slot '() down)
  51.   (add-extended-slot '() down)
  52.   (add-extended-slot '() down)
  53.   (add-extended-slot '() down)
  54.  
  55. ; these are the forty theives in the tableau
  56.   (deal-cards-face-up 0 '(10 11 12 13 14 15 16 17 18 19))
  57.   (deal-cards-face-up 0 '(10 11 12 13 14 15 16 17 18 19))
  58.   (deal-cards-face-up 0 '(10 11 12 13 14 15 16 17 18 19))
  59.   (deal-cards-face-up 0 '(10 11 12 13 14 15 16 17 18 19))
  60.  
  61.   (give-status-message)
  62. ; this is the return list of (new-game) and sets the size of the 
  63. ; the playing field.
  64.   (list 10 4.5)
  65. )
  66.  
  67. (define (in-tableau? slot) 
  68.   (and (>= slot 10) (<= slot 19))
  69. )
  70.  
  71. (define (in-foundation? slot) 
  72.   (and (>= slot 1) (<= slot 8))
  73. )
  74.  
  75. (define (in-tableau-or-waste? slot) 
  76.   (or (in-tableau? slot) (= slot waste-pile))
  77. )
  78.  
  79. (define waste-pile 9)
  80. (define stock-pile 0) 
  81. (define start-with-waste 9)
  82. (define start-with-tableau 10)
  83.  
  84. (define (<> a b) 
  85.    (not (= a b))
  86. )
  87.  
  88. (define (give-status-message)
  89.   (set-statusbar-message (get-stock-no-string)))
  90.  
  91. (define (get-stock-no-string)
  92.   (string-append (_"Stock left:") " " 
  93.          (number->string (length (get-cards 0)))
  94.   )
  95. )
  96.  
  97. ; Apparently this is used to allow a group of cards to be dragged. 
  98. ; if it returns #t then the cards are picked.
  99. ; single cards can always be pulled from waste or tableau
  100. ; multiple cards must be straight suit descending
  101. ; (droppable?) will sort out more restrictions later
  102.  (define (button-pressed slot-id card-list)
  103.   (and (not (empty-slot? slot-id))
  104.        (in-tableau-or-waste? slot-id)
  105.        ( or (= (length card-list) 1)
  106.                (and (in-tableau? slot-id)
  107.                     (check-straight-descending-list card-list)
  108.                  (check-same-suit-list card-list)    
  109.         )
  110.        )
  111.   )
  112. )
  113.  
  114. ;scoring  5*cards + 13 per suit completed.
  115. (define (foundation-score slot-id prev-total)
  116.   (define (current-total)
  117.     (+ prev-total
  118.        (* (length (get-cards slot-id)) 5)
  119.        (if (= (length (get-cards slot-id)) 13)
  120.            60
  121.            0)))
  122.   (if (= slot-id 8)
  123.       (current-total)
  124.       (foundation-score (+ slot-id 1) (current-total))))
  125.        
  126. (define (recalculate-score)
  127.   (set-score!  (foundation-score 1 0)))
  128.  
  129. ; counts empty slots in tableau
  130. (define (space-score slot-id prev)
  131.  (define (curtot previous) (+ previous (if (empty-slot? slot-id) 1 0)))
  132.  (if (= slot-id 19) (curtot prev) (space-score (+ slot-id 1) (curtot prev)))
  133. )
  134. (define (tableau-spaces) 
  135.    (space-score start-with-tableau 0)
  136. )
  137.  
  138. ; To save effort a pile of correctly descending same suit cards can be moved
  139. ; from the tableau to a foundation in one go.
  140.  
  141. ( define (foundation-droppable? card-list f-slot) 
  142.    (and (check-same-suit-list card-list)
  143.         (check-straight-descending-list card-list) 
  144.     (cond ( (empty-slot? f-slot)  
  145.                     (= (get-value (car card-list)) ace) 
  146.               )
  147.               (    ( = (get-value (car card-list)) (+ (get-value (get-top-card f-slot)) 1))
  148.             ( = (get-suit (get-top-card f-slot)) (get-suit (car card-list)))
  149.           )    
  150.               (else #f)
  151.     )
  152.    )
  153. )
  154.  
  155. ; the maximum number of cards you can move as a short cut in one go 
  156. ; depends on the number of free tableau slot (it's 2^tableau slots)
  157. ; if the pile is going to an empty-slot than that slot is not really 
  158. ; an empty slot. If the pile is the entire contents of a tableau slot
  159. ; then (tableau-spaces) reports a 'false' extra space. hence the 
  160. ; extra code.
  161. ( define (max-move-in-tableau from-slot to-slot)
  162.     (expt 2 (max 0 
  163.                  (- 
  164.             (- (tableau-spaces) (if (empty-slot? to-slot) 1 0))
  165.                (if (empty-slot? from-slot) 1 0)
  166.          )
  167.             )        
  168.     )
  169. )
  170.  
  171. ; A bunch of cards may be dropped on to a tableau slot iff
  172. ; They are a descending same suit sequence that fits the top
  173. ; card of the tableau slot or an empty slot.
  174. ; this is a short cut to save moving cards individually
  175. ( define (tableau-droppable? s-slot card-list t-slot) 
  176.    (and 
  177.     (check-same-suit-list card-list)
  178.         (check-straight-descending-list card-list)
  179.     (<= (length card-list) (max-move-in-tableau s-slot t-slot))
  180.     (cond ( (empty-slot? t-slot)  #t )
  181.               (    ( = (+ (get-value (car card-list)) (length card-list)) (get-value (get-top-card t-slot)) )
  182.             ( = (get-suit (get-top-card t-slot)) (get-suit (car card-list)))
  183.           )    
  184.               (else #f) 
  185.     )
  186.    )
  187. )
  188.  
  189.  
  190. ; droppable means that a list of cards coming from start-slot 
  191. ; and going to end-slot are valid to be moved. 
  192. ; picking up and dropping cards where they are is a null move.
  193. ; picking things off a foundation is a not permitted.
  194. ; dropping a valid pile onto a foundation is OK.
  195. ; if we are dropping onto another tableau pile sometimes OK.
  196. ; dropping card(s) elsewhere is not permitted.
  197.  
  198. (define (droppable?  start-slot card-list  end-slot) 
  199.   (cond ( (= end-slot start-slot)  #f)
  200.     ( (in-foundation? start-slot) #f)
  201.         ( (in-foundation? end-slot) (foundation-droppable? card-list end-slot) )
  202.     ( (in-tableau? end-slot) (tableau-droppable? start-slot card-list end-slot) )
  203.     (else #f)
  204.   )
  205. )
  206.  
  207. ;drop the dragged card(s) a pile of cards have to be revered 
  208. ; onto a foundation
  209. (define (button-released start-slot card-list end-slot)
  210.   (and (droppable? start-slot card-list end-slot)
  211.        (if (in-tableau? end-slot) 
  212.              (move-n-cards! start-slot end-slot card-list)
  213.              (move-n-cards! start-slot end-slot (reverse card-list) )
  214.        )
  215.        (recalculate-score)
  216.    )
  217. )
  218.  
  219. ; return "a move" if a card can be moved from from-slot to a foundation
  220. ; a move is a list either (#f) or (#t from-slot to-slot)
  221. ; no cards are actually moved this is a helper for both double-click
  222. ; and get-hint features.
  223.  
  224. (define (try-all-foundations from-slot card )
  225.     (if (not (empty-slot? from-slot))
  226.       (if (foundation-droppable? (list card) 1) 
  227.         (list #t from-slot 1)
  228.         (if (foundation-droppable? (list card) 2) 
  229.       (list #t from-slot 2)
  230.           (if (foundation-droppable? (list card) 3) 
  231.         (list #t from-slot 3)
  232.             (if (foundation-droppable? (list card) 4) 
  233.           (list #t from-slot 4)
  234.               (if (foundation-droppable? (list card) 5) 
  235.              (list #t from-slot 5)
  236.                  (if (foundation-droppable? (list card) 6) 
  237.                (list #t from-slot 6)
  238.            (if (foundation-droppable? (list card) 7) 
  239.                  (list #t from-slot 7)
  240.                      (if (foundation-droppable? (list card) 8) 
  241.                    (list #t from-slot 8)
  242.                        (list #f)
  243.        ) ) ) ) ) ) ) )
  244.        (list #f)
  245.      )
  246. )
  247.  
  248.  
  249. ; return a move if a card can be moved from from-slot to a tableau
  250. ; slot. This is a helper for hint, and double-click
  251. (define (find-tableau-place from-slot card )
  252.     (if (not (empty-slot? from-slot))
  253.       (if (and (tableau-droppable? from-slot (list card) 10) (<> from-slot 10) )
  254.         (list #t from-slot 10)
  255.         (if (and (tableau-droppable? from-slot (list card) 11) (<> from-slot 11) )
  256.       (list #t from-slot 11)
  257.           (if (and (tableau-droppable? from-slot (list card) 12) (<> from-slot 12) )
  258.         (list #t from-slot 12)
  259.             (if (and (tableau-droppable? from-slot (list card) 13) (<> from-slot 13) )
  260.           (list #t from-slot 13)
  261.               (if (and (tableau-droppable? from-slot (list card) 14) (<> from-slot 14) )
  262.             (list #t from-slot 14)
  263.                 (if (and (tableau-droppable? from-slot (list card) 15) (<> from-slot 15) )
  264.               (list #t from-slot 15)
  265.                   (if (and (tableau-droppable? from-slot (list card) 16) (<> from-slot 16) )
  266.                 (list #t from-slot 16)
  267.                     (if (and (tableau-droppable? from-slot (list card) 17) (<> from-slot 17) )
  268.                   (list #t from-slot 17)
  269.                       (if (and (tableau-droppable? from-slot (list card) 18) (<> from-slot 18) )
  270.                     (list #t from-slot 18)
  271.                         (if (and (tableau-droppable? from-slot (list card) 19) (<> from-slot 19) )
  272.                       (list #t from-slot 19)
  273.                           (list #f)
  274.       ) ) ) ) ) ) ) ) ) ) 
  275.       (list #f)
  276.     )
  277. )
  278.  
  279.  
  280.  
  281.  
  282. ;deals cards from deck to waste
  283. (define (button-clicked slot-id)
  284.   (and (= slot-id stock-pile)
  285.        (not (empty-slot? slot-id))
  286.        (deal-cards-face-up stock-pile (list waste-pile))
  287.        (recalculate-score)
  288.   )
  289. )
  290.  
  291. ; if we can find a move to the foundations do it and return #t or #f.
  292. (define (move-to-foundation) 
  293.        (let ((move (find-any-move-to-foundation waste-pile))) 
  294.       (if (car move) (deal-cards-face-up (car (cdr move)) (list (car (reverse move))) ) #f ) 
  295.        )
  296. )
  297.  
  298. ; search for any valid move to a foundation 
  299. ; helper code for both hint, autoplay
  300. (define (find-any-move-to-foundation begin-slot) 
  301.   (if (in-tableau-or-waste? begin-slot)
  302.         (let ((test (try-all-foundations begin-slot (get-top-card begin-slot)) ))
  303.              (if (car test) 
  304.                  test 
  305.                  (find-any-move-to-foundation (+ begin-slot 1)) 
  306.              )
  307.         )
  308.         (list #f)     
  309.   )
  310. )
  311.  
  312. ; search for any valid move around the tableau 
  313. ; helper code for hint
  314. (define (find-any-move-in-tableau begin-slot) 
  315.   (if (in-tableau-or-waste? begin-slot)
  316.         (let ((test (find-tableau-place begin-slot (get-top-card begin-slot)) ))
  317.              (if (car test) 
  318.                  test 
  319.                  (find-any-move-in-tableau (+ begin-slot 1)) 
  320.              )
  321.         )
  322.         (list #f)     
  323.   )
  324. )
  325.  
  326.  
  327.  
  328. (define (autoplay-foundations)
  329. (if (move-to-foundation) (autoplay-foundations) (recalculate-score))
  330. )
  331.  
  332. ; double click foundation for autoplay, otherwise does auto
  333. ; single move to foundation, or waste to tableau if poss.
  334. (define (button-double-clicked slot-id)
  335.   (cond ( (in-foundation? slot-id ) (autoplay-foundations))
  336.         ( (in-tableau-or-waste? slot-id) 
  337.             (let ((test (try-all-foundations slot-id (get-top-card slot-id)) ))
  338.           (if (car test) 
  339.                  (deal-cards-face-up (car (cdr test)) (list (car (reverse test))) ) 
  340.                  (let ((jump (find-tableau-place slot-id (get-top-card slot-id)) ))
  341.                     (if (car jump) 
  342.                        (deal-cards-face-up (car (cdr jump)) (list (car (reverse jump))) )
  343.                        #f
  344.                     )
  345.                  )
  346.               ) 
  347.             )
  348.           )
  349.     (else #f)
  350.    )
  351. )
  352.  
  353.  
  354. (define (game-continuable)
  355.   (give-status-message)
  356.   (and (not (game-won))
  357.        (get-hint)
  358.   )
  359. )
  360.  
  361.  
  362.  
  363. (define (game-won)
  364.   (and (= (length (get-cards 1)) 13)
  365.        (= (length (get-cards 2)) 13)
  366.        (= (length (get-cards 3)) 13)
  367.        (= (length (get-cards 4)) 13)
  368.        (= (length (get-cards 5)) 13)
  369.        (= (length (get-cards 6)) 13)
  370.        (= (length (get-cards 7)) 13)
  371.        (= (length (get-cards 8)) 13)
  372.   )
  373. )
  374.  
  375.  
  376. ;this is the last-straw hint maker
  377. (define (check-for-deal)
  378.   (if (not (empty-slot? stock-pile)) 
  379.         (list 0 (_"Deal a card from stock"))
  380.      #f
  381.   )
  382. )
  383.  
  384. ; turn a 'move' into a text description for get-hint.
  385. (define (make-destination-hint slot)
  386.     (if (in-foundation? slot)
  387.        (if (empty-slot? slot) 
  388.                 (_"an empty foundation") 
  389.         (get-name (get-top-card slot))
  390.        )
  391.        (if (empty-slot? slot) 
  392.         (_"an empty space")
  393.         (get-name (get-top-card slot)) 
  394.        )
  395.     )
  396.  
  397. (define (make-hint move)
  398.     (if (car move) 
  399.        (list 2 (get-name (get-top-card (car (cdr move))))
  400.                (make-destination-hint (car (reverse move))) 
  401.        )     
  402.        (list 0 (_"Bug! make-hint called on false move.") )
  403.     )
  404. )
  405.  
  406.  
  407.  
  408. ; hint  suggests the following in order:
  409. ;  a move to a foundation from waste or tableau
  410. ;  move the top waste card to a valid tableau space or pile
  411. ;  move some other tableau card to another tableau space or pile 
  412. ;  deal a card or at end backup and try alternatives.
  413. ; these are not intended to be a the best moves simply to show 
  414. ; possible moves to help learn the rules.
  415. (define (get-hint)
  416.   (cond ( (car (find-any-move-to-foundation start-with-waste))
  417.           (make-hint (find-any-move-to-foundation start-with-waste)) 
  418.         ) 
  419.         ( (and (not (empty-slot? waste-pile)) 
  420.                (car (find-tableau-place waste-pile (get-top-card waste-pile) ) ) 
  421.           )
  422.           (make-hint (find-tableau-place waste-pile (get-top-card waste-pile)))
  423.         )
  424.         ( (car (find-any-move-in-tableau start-with-tableau) ) 
  425.           (make-hint (find-any-move-in-tableau start-with-tableau ) )
  426.         )
  427.         (else (check-for-deal))
  428.   )
  429. )
  430.  
  431. (define (get-options) 
  432.   #f)
  433.  
  434. (define (apply-options options) 
  435.   #f)
  436.  
  437. (define (timeout) 
  438.   #f)
  439.  
  440. (set-features droppable-feature)
  441.  
  442. (set-lambda new-game button-pressed button-released button-clicked
  443. button-double-clicked game-continuable game-won get-hint get-options
  444. apply-options timeout droppable?)
  445.